#pragma once

#include<iostream>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<string.h>
#include<functional>
#include<string>
#include<pthread.h>
#include<time.h>

#include"Log.hpp"
#include"InetAddr.hpp"
#include"Protocal.hpp"

class Client
{
public:
    Client(int ip,int port)
    :_is_running(false)
    {
        bzero(&_server_addr,sizeof(_server_addr));
        _server_addr.sin_addr.s_addr=ip;
        _server_addr.sin_family=AF_INET;
        _server_addr.sin_port=port;

        _sockfd=socket(AF_INET,SOCK_STREAM,0);
        if(0>_sockfd)
        {
            Log(FATAL,"create sockfd error\n");
            exit(-1);
        }
        Log(DEBUG,"create sockfd successfully\n");
    }

    void Start()
    {
        _is_running=true;
        srand(time(nullptr));
        if(0>connect(_sockfd,(struct sockaddr*)&_server_addr,sizeof(_server_addr)))
        {
            Log(FATAL,"connect fail\n");
            exit(-1);
        }

        std::string operas("+-*/");
        while(_is_running)
        {
            //std::string in;
            //std::cin>>in;

            //生成随机请求
            int x=rand()%100;
            int y=rand()%100;
            char opera=operas[(rand()%3+4)%4];
            protocal::Request request(x,y,opera);
            //序列化请求
            std::string request_json_str;
            request.SerializeRequest(request_json_str);

            //封装自定义协议
            std::string request_str=protocal::Encode(request_json_str);

            //向服务端发送请求报文
            char request_buf[1024];
            strcpy(request_buf,request_str.c_str());
            int wn=write(_sockfd,request_buf,sizeof(request_buf));
            if(wn<0)
            {
                Log(ERROR,"write fail\n");
                continue;
            }

            std::string inbuf;
            while(_is_running)
            {
                char response_buf[1024];
                int rn = read(_sockfd,response_buf,sizeof(response_buf));
                if(rn<=0)
                {
                    Log(ERROR,"read fail\n");
                    _is_running=false;
                    break;
                }
                inbuf+=response_buf;

                //对应答进行解析获取一个完整报文
                std::string response_json_str=protocal::Decode(inbuf);
                if(response_json_str.empty())
                {
                    continue;
                }

                //对报文进行反序列化
                protocal::Response response;
                response.DeserializeResponse(response_json_str);

                //处理返回结果
                if(0==response._stat)
                {
                    printf("%d %c %d = %0.2f\n",x,opera,y,response._result);
                }
                else if(1==response._stat)
                {
                    std::cout<<"no such operator"<<std::endl;
                }
                else if(2==response._stat)
                {
                    std::cout<<"div zero error"<<std::endl;
                }
                else
                {
                    std::cout<<"unknow error"<<std::endl;
                }
                break;
            }
            sleep(1);
        }
    }

    ~Client()
    {
        if(0<_sockfd)
        {
            close(_sockfd);
        }
    }

private:
    int _sockfd;
    struct sockaddr_in _server_addr;
    bool _is_running;
};